package com.unitd.frame.comm.utils.http;

import com.unitd.frame.comm.exception.SysRunTimeException;
import com.unitd.frame.comm.utils.CharsetUtils;
import com.unitd.frame.comm.utils.EnvUtils;
import com.unitd.frame.comm.utils.ExceptionUtils;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpClientParams;
import com.unitd.frame.comm.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.net.ssl.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.*;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.cert.X509Certificate;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.zip.GZIPInputStream;

import static com.unitd.frame.comm.utils.ExceptionUtils.unchecked;

/**
 * @desc http操作工具类
 * @filename HttpUtils.java
 * @copyright www.unitd.com
 * @author Hudan
 * @version 1.0
 * @date 2017/4/29
 */
public class HttpUtils {

	private static final Logger logger = LoggerFactory.getLogger(HttpUtils.class.getName());

	public static final String DEFAULT_CHARSET = CharsetUtils.UTF_8.name();
	private static final String METHOD_POST = "POST";
	private static final String METHOD_GET = "GET";
	private static final String CONTENT_ENCODING_GZIP = "gzip";

	private HttpUtils() {
	}

	/**
	 * @desc HTTP的Get请求
	 * @param requestUrl 请求URL
	 * @return HttpResponseEntity
	 */
	public static HttpResponseEntity doGet(String requestUrl) {
		return doGet(requestUrl, HttpRequestEntity.create());
	}

	/**
	 * @desc HTTP的Get请求
	 * @param requestUrl 请求URL
	 * @param requestEntity 请求参数对象
	 * @return HttpResponseEntity
	 */
	public static HttpResponseEntity doGet(String requestUrl, HttpRequestEntity requestEntity) {
		HttpURLConnection conn = null;
		HttpResponseEntity response;

		try {
			String ctype = "application/json;charset=" + requestEntity.getCharset();
			// 创建
			String query = buildQuery(requestEntity.getTextParams(), requestEntity.getCharset());
			// 根据请求参数和请求根URL,创建响应的全请求URL,并发起请求
			conn = getConnection(buildGetUrl(requestUrl, query), METHOD_GET, ctype, requestEntity);

			response = getResponseAsResponseEntity(conn);
		} catch (Exception e) {
			response = new HttpResponseEntity(400, e);
		} finally {
			if (conn != null) {
				conn.disconnect();
			}
		}

		return response;
	}

	/**
	 * @desc HTTP的Post请求
	 * @param requestUrl 请求URL
	 * @param requestEntity 请求参数对象
	 * @return HttpResponseEntity
	 */
	public static HttpResponseEntity doPost(String requestUrl, HttpRequestEntity requestEntity) {
		HttpURLConnection conn = null;
		HttpResponseEntity response;
		OutputStream out = null;
		String contextType;

		try {
			if (requestEntity.getFileParams().isEmpty()) {
				contextType = "application/x-www-form-urlencoded;charset=" + requestEntity.getCharset();
				conn = getConnection(new URL(requestUrl), METHOD_POST, contextType, requestEntity);
				out = conn.getOutputStream();

				String query = buildQuery(requestEntity.getTextParams(), requestEntity.getCharset());
				byte[] content = {};
				if (query != null) {
					content = query.getBytes(requestEntity.getCharset());
				}
				conn.setRequestProperty("Content-Length", String.valueOf(content.length));
				out.write(content);
			} else {
				// 随机分隔线
				String boundary = String.valueOf(System.nanoTime());
				contextType = "multipart/form-data;charset=" + requestEntity.getCharset() + ";boundary=" + boundary;
				conn = getConnection(new URL(requestUrl), METHOD_POST, contextType, requestEntity);
				out = conn.getOutputStream();

				byte[] entryBoundaryBytes = ("\r\n--" + boundary + "\r\n").getBytes(requestEntity.getCharset());

				// 组装文本请求参数
				Set<Entry<String, String>> textEntrySet = requestEntity.getTextParams().entrySet();
				for (Entry<String, String> textEntry : textEntrySet) {
					byte[] textBytes = getTextEntry(textEntry.getKey(), textEntry.getValue(), requestEntity.getCharset());
					out.write(entryBoundaryBytes);
					out.write(textBytes);
				}

				// 组装文件请求参数
				Set<Entry<String, HttpRequestEntity.FileItem>> fileEntrySet = requestEntity.getFileParams().entrySet();
				for (Entry<String, HttpRequestEntity.FileItem> fileEntry : fileEntrySet) {
					HttpRequestEntity.FileItem fileItem = fileEntry.getValue();
					if (fileItem.getContent() == null) {
						continue;
					}
					byte[] fileBytes = getFileEntry(fileEntry.getKey(), fileItem.getFileName(), fileItem.getMimeType(), requestEntity.getCharset());
					out.write(entryBoundaryBytes);
					out.write(fileBytes);
					out.write(fileItem.getContent());
				}

				// 添加请求结束标志
				byte[] endBoundaryBytes = ("\r\n--" + boundary + "--\r\n").getBytes(requestEntity.getCharset());
				out.write(endBoundaryBytes);
			}

			response = getResponseAsResponseEntity(conn);
		} catch (Exception e) {
			response = new HttpResponseEntity(400, e);
		} finally {
			if (out != null) {
				try {
					out.close();
				} catch (Exception e2) {
				}
			}
			if (conn != null) {
				conn.disconnect();
			}
		}
		return response;
	}

	/**
	 * @desc HTTP的Post请求
	 * @param requestUrl 请求URL
	 * @param json 请求的json参数
	 * @param charset 编码
	 * @return HttpResponseEntity
	 */
	public static HttpResponseEntity doPost(String requestUrl, String json, String charset) {
		HttpURLConnection conn = null;
		HttpResponseEntity response;
		OutputStream out = null;

		try {
			String ctype = "application/json;charset=" + charset;
			conn = getConnection(new URL(requestUrl), METHOD_POST, ctype, HttpRequestEntity.create().charset(charset));
			byte[] data = json.getBytes();
			conn.setRequestProperty("Content-Length", String.valueOf(data.length));
			out = conn.getOutputStream();
			out.write(data);
			out.flush();
			response = getResponseAsResponseEntity(conn);
		} catch (IOException e) {
			response = new HttpResponseEntity(400, e);
		} finally {
			if (out != null) {
				try {
					out.close();
				} catch (Exception e) {
					response = new HttpResponseEntity(400, e);
				}
			}
			if (conn != null) {
				conn.disconnect();
			}
		}

		return response;
	}

	/**
	 * @desc HTTP上传
	 * @param requestUrl 请求URL
	 * @param fieldName 文件名称
	 * @param file 上传文件对象
	 * @return HttpResponseEntity
	 */
	public static HttpResponseEntity doUpload(String requestUrl, String fieldName, File file) {
		return doPost(requestUrl, HttpRequestEntity.create().addFileParam(fieldName, new HttpRequestEntity.FileItem(file)));
	}

	/**
	 * @desc 根据文件URL下载该文件到指定路径
	 * @param fileURL 文件URL
	 * @param saveDir 保存路径
	 * @return String
	 */
	public static String downloadFile(String fileURL, String saveDir) {
		HttpURLConnection httpConn = null;
		FileOutputStream outputStream = null;
		try {
			URL url = new URL(fileURL);
			httpConn = (HttpURLConnection) url.openConnection();
			int responseCode = httpConn.getResponseCode();

			if (responseCode == HttpURLConnection.HTTP_OK) {
				String fileName = "";
				String disposition = httpConn.getHeaderField("Content-Disposition");

				if (disposition != null) {
					int index = disposition.indexOf("filename=");
					if (index > 0) {
						fileName = disposition.substring(index + 10,
								disposition.length() - 1);
					}
				} else {
					fileName = fileURL.substring(fileURL.lastIndexOf("/") + 1,
							fileURL.length());
				}
				InputStream inputStream = httpConn.getInputStream();
				String saveFilePath = saveDir + File.separator + fileName;
				outputStream = new FileOutputStream(saveFilePath);

				int bytesRead;
				byte[] buffer = new byte[2048];
				while ((bytesRead = inputStream.read(buffer)) != -1) {
					outputStream.write(buffer, 0, bytesRead);
				}

				outputStream.close();
				inputStream.close();
				return saveFilePath;
			} else {
				throw new SysRunTimeException("下载失败", responseCode);
			}
		} catch (IOException e) {
			throw new SysRunTimeException("下载失败", 500, e);
		} finally {
			try {
				if (outputStream != null) {
					outputStream.close();
				}
			} catch (Exception e) {
				throw new SysRunTimeException("下载失败", 500, e);
			}
			try {
				if (httpConn != null) {
					httpConn.disconnect();
				}
			} catch (Exception e) {
				throw new SysRunTimeException("下载失败", 500, e);
			}
		}
	}

	/**
	 * @desc 获取请求对象的属性信息
	 * @param fieldName 请求名称
	 * @param fieldValue 请求值
	 * @param charset 编码
	 * @return byte[]
	 */
	private static byte[] getTextEntry(String fieldName, String fieldValue, String charset) throws IOException {
		StringBuilder entry = new StringBuilder();
		entry.append("Content-Disposition:form-data;name=\"");
		entry.append(fieldName);
		entry.append("\"\r\nContent-Type:text/plain\r\n\r\n");
		entry.append(fieldValue);
		return entry.toString().getBytes(charset);
	}

	/**
	 * @desc 获取文件对象的属性信息
	 * @param fieldName 请求名称
	 * @param fileName 文件名称
	 * @param mimeType 文件类型
	 * @param charset 编码
	 * @return byte[]
	 */
	private static byte[] getFileEntry(String fieldName, String fileName, String mimeType, String charset) {
		try {
			StringBuilder entry = new StringBuilder();
			entry.append("Content-Disposition:form-data;name=\"");
			entry.append(fieldName);
			entry.append("\";filename=\"");
			entry.append(fileName);
			entry.append("\"\r\nContent-Type:");
			entry.append(mimeType);
			entry.append("\r\n\r\n");

			return entry.toString().getBytes(charset);
		} catch (UnsupportedEncodingException e) {
			throw unchecked(e);
		}
	}

	/**
	 * @desc 根据请求参数创建,拼装请求
	 * @param params 请求参数
	 * @param charset 编码格式
	 * @return 请求串
	 */
	private static String buildQuery(Map<String, String> params, String charset) {
		if (params == null || params.isEmpty()) {
			return null;
		}

		StringBuilder query = new StringBuilder();
		Set<Entry<String, String>> entries = params.entrySet();
		boolean hasParam = false;

		for (Entry<String, String> entry : entries) {
			String name = entry.getKey();
			String value = entry.getValue();
			// 忽略参数名或参数值为空的参数
			if (StringUtils.isAnyEmpty(name, value)) {
				if (hasParam) {
					query.append("&");
				} else {
					hasParam = true;
				}

				try {
					query.append(name).append("=").append(URLEncoder.encode(value, charset));
				} catch (UnsupportedEncodingException e) {
					throw unchecked(e);
				}
			}
		}

		return query.toString();
	}

	/**
	 * @desc 根据请求参数和请求根URL,创建响应的全请求URL
	 * @param requestUrl 请求URL
	 * @param query 请求参数串
	 * @return URL
	 */
	private static URL buildGetUrl(String requestUrl, String query) {
		try {
			URL url = new URL(requestUrl);
			if (StringUtils.isEmpty(query)) {
				return url;
			}

			if (StringUtils.isEmpty(url.getQuery())) {
				if (requestUrl.endsWith("?")) {
					requestUrl = requestUrl + query;
				} else {
					requestUrl = requestUrl + "?" + query;
				}
			} else {
				if (requestUrl.endsWith("&")) {
					requestUrl = requestUrl + query;
				} else {
					requestUrl = requestUrl + "&" + query;
				}
			}
			return new URL(requestUrl);
		} catch (MalformedURLException e) {
			throw unchecked(e);
		}
	}

	/**
	 * @desc 根据请求方式(GET/POST)和请求URL以及请求参数对象,向HTTP服务端发起请求,建立连接
	 * @param url 请求URL
	 * @param method 请求方式(GET/POST)
	 * @param contextType 请求的数据类型(text/json等)
	 * @param requestEntity 请求数据对象
	 * @return HttpURLConnection
	 */
	private static HttpURLConnection getConnection(URL url, String method, String contextType, HttpRequestEntity requestEntity) {
		HttpURLConnection conn;
		try {
			conn = (HttpURLConnection) url.openConnection();
			conn.setRequestMethod(method);
			conn.setDoInput(true);
			conn.setDoOutput(true);
			conn.setRequestProperty("Accept", "*/*");
			conn.setRequestProperty("Content-Type", contextType);
			conn.setConnectTimeout(requestEntity.getConnectTimeout());
			conn.setReadTimeout(requestEntity.getReadTimeout());
			if (!requestEntity.getHeaders().isEmpty()) {
				for (Entry<String, String> entry : requestEntity.getHeaders().entrySet()) {
					conn.setRequestProperty(entry.getKey(), entry.getValue());
				}
			}
			if (requestEntity.getBasicAuth() != null) {
				conn.setRequestProperty("Authorization", requestEntity.getBasicAuth().getEncodeBasicAuth());
			}
			return conn;
		} catch (IOException e) {
			throw unchecked(e);
		}
	}

	/**
	 * @desc 获取HTTP请求服务端的响应信息,并封装到响应对象中
	 * @param conn httpq请求连接对象
	 * @return HttpResponseEntity
	 */
	private static HttpResponseEntity getResponseAsResponseEntity(HttpURLConnection conn) {
		try {
			HttpResponseEntity responseEntity = new HttpResponseEntity();
			String charset = getResponseCharset(conn.getContentType());
			InputStream es = conn.getErrorStream();
			responseEntity.setStatusCode(conn.getResponseCode());

			if (es == null) {
				String contentEncoding = conn.getContentEncoding();
				if (CONTENT_ENCODING_GZIP.equalsIgnoreCase(contentEncoding)) {
					responseEntity.setBody(getStreamAsString(new GZIPInputStream(conn.getInputStream()), charset));
				} else {
					responseEntity.setBody(getStreamAsString(conn.getInputStream(), charset));
				}
			} else {
				String msg = getStreamAsString(es, charset);
				if (StringUtils.isEmpty(msg)) {
					responseEntity.setBody(conn.getResponseCode() + ":" + conn.getResponseMessage());
				} else {
					responseEntity.setBody(msg);
				}
			}

			return responseEntity;
		} catch (IOException e) {
			throw unchecked(e);
		}
	}

	/**
	 * @desc 将数据流转换成字符串
	 * @param stream 数据流对象
	 * @param charset 编码
	 * @return String
	 */
	private static String getStreamAsString(InputStream stream, String charset) {
		try {
			Reader reader = new InputStreamReader(stream, charset);
			StringBuilder response = new StringBuilder();

			final char[] buff = new char[1024];
			int read;
			while ((read = reader.read(buff)) > 0) {
				response.append(buff, 0, read);
			}

			return response.toString();
		} catch (IOException e) {
			throw unchecked(e);
		} finally {
			if (stream != null) {
				try {
					stream.close();
				} catch (IOException e) {
					throw unchecked(e);
				}
			}
		}
	}

	/**
	 * @desc 获取响应对象的编码类型
	 * @param ctype mime 类型
	 * @return String
	 */
	private static String getResponseCharset(String ctype) {
		String charset = DEFAULT_CHARSET;

		if (!StringUtils.isEmpty(ctype)) {
			String[] params = ctype.split(";");
			for (String param : params) {
				param = param.trim();
				if (param.startsWith("charset")) {
					String[] pair = param.split("=", 2);
					if (pair.length == 2) {
						if (!StringUtils.isEmpty(pair[1])) {
							charset = pair[1].trim();
						}
					}
					break;
				}
			}
		}

		return charset;
	}

	/**
	 * @param url http的ping请求
	 * @return 请求的服务端相应代码 200 为正常
	 * @desc http客户端ping服务端, 得到服务端相应代码
	 */
	public static int ping(String url) {
		HttpClient httpclient = new HttpClient();
		GetMethod get = new GetMethod(url);
		try {
			return httpclient.executeMethod(get);
		} catch (IOException e) {
			System.out.println("fetch error:" + e.getLocalizedMessage());
			throw ExceptionUtils.unchecked(e);
		} finally {
			get.releaseConnection();
		}
	}

	/**
	 * @desc http的Get请求, 根据get请求, 获取该请求的结果串
	 * @param url http的get请求
	 * @return 请求的结果串
	 */
	public static String doHttpGet(String url) {
		HttpClient httpclient = new HttpClient();
		GetMethod get = new GetMethod(url);
		String result = null;
		try {
			int status = httpclient.executeMethod(get);
			if (status == HttpStatus.SC_OK) {
				result = get.getResponseBodyAsString();
			}
		} catch (IOException e) {
			System.out.println("fetch error:" + e.getLocalizedMessage());
			throw ExceptionUtils.unchecked(e);
		} finally {
			get.releaseConnection();
		}
		return result;
	}

	/**
	 * @desc http的Post请求, 根据post请求, 获取该请求的结果串
	 * @param url    http的post请求
	 * @param params 请求参数
	 * @return 请求的结果串
	 */
	public static String doHttpPost(String url, Map params) {
		HttpClient httpclient = new HttpClient();
		HttpClientParams httpClientParams = new HttpClientParams();
		httpClientParams.setSoTimeout(1000 * 30);
		httpClientParams.setContentCharset("UTF-8");
		httpclient.setParams(httpClientParams);
		PostMethod post = new PostMethod(url);

		return executPostAndResponse(httpclient, post);
	}

	/**
	 * @desc http的Post请求, 根据post请求, 获取该请求的结果串
	 * @param url     http的post请求
	 * @param content 请求参数
	 * @return 请求的结果串
	 */
	public static String doHttpPost(String url, String content) {
		HttpClient httpclient = new HttpClient();
		PostMethod post = new PostMethod(url);
		post.setRequestBody(content);

		return executPostAndResponse(httpclient, post);
	}

	/**
	 * @desc 执行http的post请求, 并获取返回结果
	 * @param httpclient http请求客户端
	 * @param postMethod post方法
	 * @return 请求的结果串
	 */
	private static String executPostAndResponse(HttpClient httpclient, PostMethod postMethod) {

		String result = null;
		try {
			int status = httpclient.executeMethod(postMethod);
			if (status == HttpStatus.SC_OK) {
				result = postMethod.getResponseBodyAsString();
			}
		} catch (IOException e) {
			throw ExceptionUtils.unchecked(e);
		} finally {
			postMethod.releaseConnection();
		}
		return result;
	}

	/**
	 * @desc 根据http请求, 不分get和post请求, 获取相应响应结果
	 * @param requestUrl    http请求
	 * @param requestMethod GET/POST请求类型
	 * @param outputStr     请求参数
	 * @return 请求结果
	 */
	public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {
		String jsonObject = null;
		StringBuilder buffer = new StringBuilder();
		try {
			// 创建SSLContext对象，并使用我们指定的信任管理器初始化
			TrustManager[] tm = {new HTTPSManager()};
			SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
			sslContext.init(null, tm, new java.security.SecureRandom());
			// 从上述SSLContext对象中得到SSLSocketFactory对象
			SSLSocketFactory ssf = sslContext.getSocketFactory();
			URL url = new URL(requestUrl);
			HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
			httpUrlConn.setSSLSocketFactory(ssf);
			httpUrlConn.setDoOutput(true);
			httpUrlConn.setDoInput(true);
			httpUrlConn.setUseCaches(false);
			// 设置请求方式（GET/POST）
			httpUrlConn.setRequestMethod(requestMethod);

			if ("GET".equalsIgnoreCase(requestMethod)) {
				httpUrlConn.connect();
			}

			// 当有数据需要提交时
			if (null != outputStr) {
				OutputStream outputStream = httpUrlConn.getOutputStream();
				// 注意编码格式，防止中文乱码
				outputStream.write(outputStr.getBytes("UTF-8"));
				outputStream.close();
			}
			// 将返回的输入流转换成字符串
			InputStream inputStream = httpUrlConn.getInputStream();
			InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
			BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
			String str;
			while ((str = bufferedReader.readLine()) != null) {
				buffer.append(str);
			}
			bufferedReader.close();
			inputStreamReader.close();
			// 释放资源
			inputStream.close();
			httpUrlConn.disconnect();
			jsonObject = buffer.toString();
		} catch (IOException | NoSuchAlgorithmException | NoSuchProviderException | KeyManagementException e) {
			throw ExceptionUtils.unchecked(e);
		}
		return jsonObject;
	}

	/**
	 * @desc 获取http请求对象
	 * @return HttpServletRequest
	 */
	public static HttpServletRequest getHttpServletRequest() {
		return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
	}

	/**
	 * @desc 根据请求的url, 获取该请求得到的字符串数据
	 * @param requestURL http请求URL
	 * @return 请求结果
	 */
	public static String getHttpResponse(String requestURL) {
		BufferedReader in = null;
		StringBuffer result;
		try {
			URI uri = new URI(requestURL);
			URL url = uri.toURL();
			URLConnection connection = url.openConnection();
			connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
			connection.setRequestProperty("Charset", "utf-8");
			connection.connect();

			result = new StringBuffer();
			// 读取URL的响应
			in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
			String line;
			while ((line = in.readLine()) != null) {
				result.append(line);
			}
			return result.toString();
		} catch (Exception e) {
			throw ExceptionUtils.unchecked(e);
		} finally {
			try {
				if (in != null) {
					in.close();
				}
			} catch (Exception e) {
				throw ExceptionUtils.unchecked(e);
			}
		}
	}

	/**
	 * @desc 允许 JS 跨域设置
	 * 使用 nginx 注意需在 nginx.conf 中配置
	 * http {
	 * add_header Access-Control-Allow-Origin *;
	 * }
	 * 非 ngnix 下,如果该方法设置不管用、可以尝试增加下行代码
	 * response.setHeader("Access-Control-Allow-Origin", "*");
	 * @param response 响应请求
	 */
	public static void allowJsCrossDomain(HttpServletResponse response) {
		response.setHeader("Access-Control-Allow-Credentials", "true");
		response.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS, POST, PUT, DELETE");
		response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
		response.setHeader("Access-Control-Max-Age", "3600");
	}

	/**
	 * @desc 判断请求是否为 AJAX
	 * @param request 当前请求
	 * @return boolean
	 */
	public static boolean isAjax(HttpServletRequest request) {
		return (request.getHeader("X-Requested-With") != null
				&& "XMLHttpRequest".equals(request.getHeader("X-Requested-With")));
	}

	/**
	 * @desc AJAX 设置 response 返回状态
	 * @param response http响应
	 * @param status   HTTP 状态码
	 * @param tip      消息说明
	 */
	public static void ajaxStatus(HttpServletResponse response, int status, String tip) {
		try {
			response.setContentType("text/html;charset=" + EnvUtils.SYS_DEF_ENCODING);
			response.setStatus(status);
			PrintWriter out = response.getWriter();
			out.print(tip);
			out.flush();
		} catch (IOException e) {
			logger.error(e.toString());
			throw ExceptionUtils.unchecked(e);
		}
	}

	/**
	 * @desc 获取当前 URL 包含查询条件
	 * @param request http请求对象
	 * @param encode  URLEncoder编码格式
	 * @return String
	 */
	public static String getQueryString(HttpServletRequest request, String encode) {
		try {
			StringBuilder sb = new StringBuilder(request.getRequestURL());
			String query = request.getQueryString();
			if (query != null && query.length() > 0) {
				sb.append("?").append(query);
			}
			return URLEncoder.encode(sb.toString(), encode);
		} catch (IOException e) {
			throw ExceptionUtils.unchecked(e);
		}
	}

	/**
	 * @desc 判断当前请求是否包含在指定的URL之内
	 * @param request http请求对象
	 * @param url     参数为以';'分割的URL字符串
	 * @return boolean
	 */
	public static boolean inContainURL(HttpServletRequest request, String url) {
		boolean result = false;
		if (StringUtils.isNotBlank(url)) {
			String[] urlArr = url.split(";");
			StringBuilder reqUrl = new StringBuilder(request.getRequestURL());

			for (String str : urlArr) {
				if (reqUrl.indexOf(str) > 1) {
					result = true;
					break;
				}
			}
		}
		return result;
	}

	/**
	 * @desc 加密返回地址
	 * @param url      跳转地址
	 * @param retParam 返回地址参数名
	 * @param retUrl   返回地址
	 * @return 加密后的返回地址
	 */
	public static String encodeRetURL(String url, String retParam, String retUrl) {
		return encodeRetURL(url, retParam, retUrl, null);
	}

	/**
	 * @desc 解密返回地址
	 * @param url      跳转地址
	 * @param retParam 返回地址参数名
	 * @param retUrl   返回地址
	 * @param data     携带参数
	 * @return 解密后的返回地址
	 */
	public static String encodeRetURL(String url, String retParam, String retUrl, Map<String, String> data) {
		if (url == null) {
			return null;
		}

		StringBuilder sb = new StringBuilder(url);
		sb.append("?");
		sb.append(retParam);
		sb.append("=");
		try {
			sb.append(URLEncoder.encode(retUrl, EnvUtils.SYS_DEF_ENCODING));
		} catch (UnsupportedEncodingException e) {
			logger.error("encodeRetURL error." + url);
			throw ExceptionUtils.unchecked(e);
		}

		if (data != null) {
			for (Entry<String, String> entry : data.entrySet()) {
				sb.append("&").append(entry.getKey()).append("=").append(entry.getValue());
			}
		}
		return sb.toString();
	}

	/**
	 * @desc URLDecoder 解码地址
	 * @param url 解码地址
	 * @return String
	 */
	public static String decodeURL(String url) {
		if (url == null) {
			return null;
		}

		String retUrl;
		try {
			retUrl = URLDecoder.decode(url, EnvUtils.SYS_DEF_ENCODING);
		} catch (UnsupportedEncodingException e) {
			logger.error("decodeURL error." + url);
			throw ExceptionUtils.unchecked(e);
		}
		return retUrl;
	}

	/**
	 * @desc GET 请求
	 * @param request http请求对象
	 * @return boolean
	 */
	public static boolean isGet(HttpServletRequest request) {
		return "GET".equalsIgnoreCase(request.getMethod());
	}

	/**
	 * @desc POST 请求
	 * @param request http请求对象
	 * @return boolean
	 */
	public static boolean isPost(HttpServletRequest request) {
		return "POST".equalsIgnoreCase(request.getMethod());
	}

	/**
	 * @desc 请求重定向至地址 location
	 * @param response 请求响应
	 * @param location 重定向至地址
	 */
	public static void sendRedirect(HttpServletResponse response, String location) {
		try {
			response.sendRedirect(location);
		} catch (IOException e) {
			logger.error("sendRedirect location:" + location);
			throw ExceptionUtils.unchecked(e);
		}
	}

	/**
	 * @desc 获取Request Playload 内容
	 * @param request http请求对象
	 * @return Request Playload 内容
	 */
	public static String requestPlayload(HttpServletRequest request) {
		StringBuilder stringBuilder = new StringBuilder();
		BufferedReader bufferedReader = null;
		try {
			InputStream inputStream = request.getInputStream();
			if (inputStream != null) {
				bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
				char[] charBuffer = new char[128];
				int bytesRead;
				while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
					stringBuilder.append(charBuffer, 0, bytesRead);
				}
			} else {
				stringBuilder.append("");
			}
		} catch (IOException ex) {
			throw ExceptionUtils.unchecked(ex);
		} finally {
			if (bufferedReader != null) {
				try {
					bufferedReader.close();
				} catch (IOException ex) {
					throw ExceptionUtils.unchecked(ex);
				}
			}
		}
		return stringBuilder.toString();
	}

	/**
	 * @desc 获取当前完整请求地址
	 * @param request http请求对象
	 * @return 请求地址
	 */
	public static String getRequestUrl(HttpServletRequest request) {
		StringBuilder url = new StringBuilder();
		// 请求协议 http,https
		url.append(request.getScheme()).append("://");
		// 请求服务器
		url.append(request.getHeader("host"));
		// 工程名
		url.append(request.getRequestURI());
		if (request.getQueryString() != null) {
			// 请求参数
			url.append("?").append(request.getQueryString());
		}
		return url.toString();
	}

	/**
	 * @desc 请响应的json串反馈给前端
	 * @param response http响应对象
	 * @param json 需要响应的json信息
	 */
	public static void responseOutWithJson(HttpServletResponse response, String json) {
		// 将实体对象转换为JSON Object转换
		response.setCharacterEncoding("UTF-8");
		response.setContentType("application/json; charset=utf-8");
		PrintWriter out = null;
		try {
			out = response.getWriter();
			out.append(json);
		} catch (IOException e) {
			throw ExceptionUtils.unchecked(e);
		} finally {
			if (out != null) {
				out.close();
			}
		}
	}

	static class HTTPSManager implements X509TrustManager {
		@Override
		public void checkClientTrusted(X509Certificate[] chain, String authType) {
		}

		@Override
		public void checkServerTrusted(X509Certificate[] chain, String authType) {
		}

		@Override
		public X509Certificate[] getAcceptedIssuers() {
			return null;
		}
	}

	public static void main(String[] args) {
		//上传文件
		HttpRequestEntity entity = HttpRequestEntity.create()
				.addFileParam("file", new HttpRequestEntity.FileItem("/Users/jiangwei/Desktop/homepage.txt"))
				.basicAuth("admin", "123456");
		HttpResponseEntity responseEntity = HttpUtils.doPost("http://192.168.1.3:9082/upload", entity);
		System.out.println(responseEntity);

		// post
		responseEntity = HttpUtils.doPost("http://192.168.1.3:9082/add",
				HttpRequestEntity.create().addTextParam("name", "test")
						.addTextParam("password", "123456"));
		if (responseEntity.isSuccessed()) {
			System.out.println(responseEntity.getBody());
		}
	}
}